﻿using System;
using System.Collections.Generic;
using System.Reflection;
using feather.attr;
using Newtonsoft.Json.Linq;
using System.Diagnostics;
using System.Collections;

namespace feather.core
{
    public class ActionController
    {
        private List<ActionFinder> actionFinderList = new List<ActionFinder>();

        private IDictionary<string, ActionUnit> actionUnitMap = new Dictionary<string, ActionUnit>();

        public ActionController()
        {
        }

        public void AddObjectMethod(object obj)
        {
            Type t = obj.GetType();
            foreach (MethodInfo method in t.GetMethods())
            {
                object[] methodAttr = method.GetCustomAttributes(typeof(ActionMethod), false);
                if (methodAttr.Length == 0)
                    continue;
                AddActionUnit(method.Name, new ActionUnitMethod(obj, method, this));
            }
        }

        /// <summary>
        /// 添加一个Action寻找对象
        /// </summary>
        /// <param name="actionFinder">Action寻找对象</param>
        public void AddActionFinder(ActionFinder actionFinder)
        {
            actionFinderList.Add(actionFinder);
        }

        /// <summary>
        /// 添加一个Action单元对象
        /// </summary>
        /// <param name="name">Action单元名称</param>
        /// <param name="actionUnit">Action单元对象</param>
        public void AddActionUnit(string name, ActionUnit actionUnit)
        {
            actionUnitMap.Add(name, actionUnit);
        }

        /// <summary>
        /// 执行URI
        /// </summary>
        /// <param name="uri">URI</param>
        /// <param name="args">执行参数</param>
        /// <returns></returns>
        public object DoURI(string uri, object args)
        {
            object action = null;
            foreach (ActionFinder e in actionFinderList)
            {
                action = e.Find(uri);
                if (action != null) break;
            }

            if (action == null)
            {
                Trace.WriteLine(string.Format("uri:{0} not found", uri), "feather");
                return null;
            }

            try
            {
                return DoAction(action, args);
            }
            catch (Exception e)
            {
                Trace.WriteLine(e.StackTrace, "feather");
                return null;
            }
        }

        /// <summary>
        /// 执行Action
        /// </summary>
        /// <param name="action">Action对象</param>
        /// <param name="args">执行参数</param>
        /// <returns></returns>
        private object DoAction(object action, object args)
        {
            if (action is JObject)
            {
                JObject jsonAction = action as JObject;

                string actionName = jsonAction.Value<string>("_action");

                if (actionName != null)
                {
                    ActionUnit actionUnit = null;
                    if (actionUnitMap.TryGetValue(actionName, out actionUnit))
                    {
                        JObject inputActionMap = jsonAction.Value<JObject>("_input");
                        IDictionary<string, object> inputMap = new Dictionary<string, object>();
                        if (inputActionMap != null)
                        {
                            foreach (KeyValuePair<string, JToken> e in inputActionMap)
                            {
                                inputMap.Add(e.Key, DoAction(e.Value, args));
                            }
                        }
                        return actionUnit.Execute(inputMap);
                    }
                    Trace.WriteLine(string.Format("action:{0} not found", actionName), "feather");
                    return null;
                }
                else
                {
                    IDictionary<string, object> resultMap = new Dictionary<string, object>();
                    foreach (KeyValuePair<string, JToken> e in jsonAction)
                    {
                        resultMap.Add(e.Key, DoAction(e.Value, args));
                    }

                    return resultMap;
                }
            }
            else if (action is JArray)
            {
                JArray jsonAction = action as JArray;
                IList<object> resultList = new List<object>();
                foreach (JToken e in jsonAction)
                {
                    resultList.Add(DoAction(e, args));
                }

                return resultList;

            }
            else if (action is JValue)
            {
                JValue valAction = action as JValue;
                string strAction = valAction.Value<string>();
                if (strAction != null && strAction == "$params")
                    return args;
                return valAction.Value;
            }
            else
            {
                return action;
            }
        }

    }
}
